package com.phenix.admin.configuration;

import com.phenix.core.exception.PhenixAccessDeniedHandler;
import com.phenix.core.exception.PhenixAuthenticationEntryPoint;
import com.phenix.core.security.handler.OauthLogoutHandler;
import com.phenix.core.security.token.service.PhenixRedisTokenService;
import com.phenix.core.security.token.store.PhenixRedisTokenStore;
import com.phenix.starter.mysql.datasource.UmspscDataSource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.actuate.autoconfigure.security.servlet.EndpointRequest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.Authentication;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
import org.springframework.security.web.authentication.logout.CookieClearingLogoutHandler;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource;
import java.io.IOException;

/**
 * oauth2资源服务器配置
 *
 * @author: zhenghui
 * @date: 2019/12/19
 * @description:
 */
@Slf4j
@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {

    @Autowired
    private PhenixRedisTokenStore phenixRedisTokenStore;

    @Autowired
    private TokenEnhancer tokenEnhancer;

    private void init(){
    }
   // private BearerTokenExtractor tokenExtractor = new BearerTokenExtractor();

    @Primary
    @Bean
    public PhenixRedisTokenService phenixRedisTokenService() {
        PhenixRedisTokenService phenixRedisTokenService = new PhenixRedisTokenService();
        phenixRedisTokenService.setTokenStore(phenixRedisTokenStore);
        phenixRedisTokenService.setTokenEnhancer(tokenEnhancer);
        return phenixRedisTokenService;
    }

    @Primary
    @Bean
    public DataSource dataSource() {
        UmspscDataSource dataSource = new UmspscDataSource();
        return dataSource;
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        PasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        return passwordEncoder;
    }

    @Bean
    public JdbcClientDetailsService clientDetailsService() {
        JdbcClientDetailsService jdbcClientDetailsService = new JdbcClientDetailsService(dataSource());
        jdbcClientDetailsService.setPasswordEncoder(passwordEncoder());
        return jdbcClientDetailsService;
    }

    @Bean
    public OauthLogoutHandler oauthLogoutHandler() {
        return new OauthLogoutHandler();
    }

    /**
     * 登陆成功
     */
    @Bean
    public AuthenticationSuccessHandler loginSuccessHandler() {
        return new SavedRequestAwareAuthenticationSuccessHandler() {
            @Override
            public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response,
                                                Authentication authentication) throws IOException, ServletException {
                super.onAuthenticationSuccess(request, response, authentication);
            }
        };
    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) throws Exception{
        // 这里的签名key 保持和认证中心一致
        log.info("buildRedisTokenServices[{}]", phenixRedisTokenService());
        // 构建redis获取token服务
        resources.tokenServices(phenixRedisTokenService());
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
                .and()
                .authorizeRequests()
                // 监控端点内部放行
                .requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll()
                .anyRequest().permitAll()
                .and()
                //认证鉴权错误处理,为了统一异常处理。每个资源服务器都应该加上。
                .exceptionHandling()
                .accessDeniedHandler(new PhenixAccessDeniedHandler())
                .authenticationEntryPoint(new PhenixAuthenticationEntryPoint())
                .and()
                .csrf().disable();
    }

//
//    @Override
//    public void configure(HttpSecurity http) throws Exception {
//        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
//                .and()
//                .authorizeRequests()
//                // 监控端点内部放行
//                .requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll()
//                // fegin访问或无需身份认证
//                .antMatchers(
//                        "/authority/access",
//                        "/authority/app",
//                        "/app/*/info",
//                        "/app/client/*/info",
//                        "/feign/**",
//                        "/gateway/api/**",
//                        "/user/add/thirdParty",
//                        "/user/login",
//                        "/user/info",
//                        "/current/**",
//                        "/password/**",
//                        "/swagger-ui.html",
//                        "/login/**",
//                        "/logout/token",
//                        "/oauth/**",
//                        "/password/**",
//                        "/static/**",
//                        "/",
//                        "/index",
//                        "/login",
//                        "/welcome","/error", "/oauth/confirm_access"
//                ).permitAll()
//                // 监控端点内部放行
//                .requestMatchers(EndpointRequest.toAnyEndpoint()).permitAll()
//                .anyRequest().authenticated()
//                .and()
//                .formLogin().loginPage("/login").permitAll()
//                .and()
//                .logout().permitAll()
//                // /logout退出清除cookie
//                .addLogoutHandler(new CookieClearingLogoutHandler("token", "remember-me"))
//               // .logoutSuccessHandler(new LogoutSuccessHandler())
//                .and()
//                //认证鉴权错误处理,为了统一异常处理。每个资源服务器都应该加上。
//                .exceptionHandling()
//                .accessDeniedHandler(new PhenixAccessDeniedHandler())
//                .authenticationEntryPoint(new PhenixAuthenticationEntryPoint())
//                .and()
//                .csrf().disable();
//    }
//

}

